#include "LOK2ChatDisplay.h"

LOK2ChatDisplay::LOK2ChatDisplay(SDL_Surface *_screen, TTF_Font *_font, SDL_Event *_event,
								 SDLClipboard *_pClipboard, int _max_len)
{
	screen = _screen;
	font = _font;
	event = _event;
	max_len = _max_len;
	lines = 1;
	pClipboard = _pClipboard;
	SDL_EnableUNICODE(SDL_ENABLE);
	box.x = 0;
	box.y = 0;
	box.w = CHATWND_WIDTH;
	box.h = CHATWND_HEIGHT;
	highlight.active = false;
	highlight.start = 0;
	highlight.stop = 0;
	normalCursor = SDL_GetCursor();
	textCursor = SDL_MakeCursor(textCursorBMP);
	vector <pair <string, bool> > popupMenuInit;
	string label1 = "Copy";
	string label2 = "Select All";
	popupMenuInit.push_back(make_pair(label1, false));
	popupMenuInit.push_back(make_pair(label2, false));
	SDL_Color popupNormal = {0xFF, 0xFF, 0x00};
	SDL_Color popupGrayed = {0x77, 0x77, 0x22};
	pPopupMenu = new SDLPopupMenu(popupMenuInit, popupNormal, popupGrayed, screen, event, font, this);
	setFocus(false);
	m_ScrollStart = 0;
}

void LOK2ChatDisplay::display() {
	int w = 0, h = 0, curr_x = 0, curr_y = 0, i = 0, j = 0, k = 0;
	int start = 0, start2 = 0;;
	int last = 0;
	SDL_Surface *apply = 0;
	SDL_Color tColor;
	if(m_Data.size() > 0) {
		for(i = 0; i < m_Data.size(); i++) {
			for(j = 0; j < m_Data[i].size(); j++) {
				if(j > 0) {
					TTF_SizeText(font, m_Data[i][j].second.c_str(), &w, &h);
					lines = makeLines(m_Data[i], CHATWND_WIDTH - curr_x);
					for(k = 0; k < lines; k++) curr_y++;
					curr_y--;
				} else {
					TTF_SizeText(font, m_Data[i][j].second.c_str(), &w, &h);
					curr_x += h;
				}
			}
			curr_x = 0;
		}
		if((m_Data.size() + curr_y) * h > CHATWND_HEIGHT) {
			start = (((((m_Data.size() + curr_y) * h) - CHATWND_HEIGHT) / h)) - m_ScrollStart;
			start2 = start;
			//start - m_Data[start - 1].size() - 1;
			//printf("Okay, it's bigger than the window.., %d, %d, %d, %d\n", m_Data.size(), curr_y, h, start);
		}
	}

	curr_x = 0;
	curr_y = 0;


	for(i = 0 ; i < m_Data.size(); i++) {
		//lines = makeLines(box.w);
		for(j = 0; j < m_Data[i].size(); j++) {
			tColor.r = RED(m_Data[i][j].first);
			tColor.g = GRN(m_Data[i][j].first);
			tColor.b = BLU(m_Data[i][j].first);
			if(j > 0) {
				lines = makeLines(m_Data[i], CHATWND_WIDTH - curr_x);
				for(k = 0; k < lines; k++) {
					apply = TTF_RenderText_Solid(font, vLines[k].c_str(), tColor);
					if((i + curr_y) * apply->h > CHATWND_HEIGHT) return;
					if(!start) {
						apply_surface(box.x + curr_x, box.y + ((i + curr_y) * apply->h), apply, screen);
						curr_y++;
					} else start--;
				}
				curr_y--;
			} else {
				apply = TTF_RenderText_Solid(font, m_Data[i][j].second.c_str(), tColor);
				if((i + curr_y) * apply->h > CHATWND_HEIGHT) return;
				//box.h = lines * apply->h;
				if(!start) apply_surface(box.x + curr_x, box.y + ((i + curr_y) * apply->h), apply, screen);
				//else if(m_Data[i].size() == 1) start--;
				curr_x += apply->w;
			}
			SDL_FreeSurface(apply);
		}
		curr_x = 0;
	}
	if(highlight.start != highlight.stop) doHighlight();
	if(pPopupMenu->isVisible()) {
		if(pPopupMenu->mustRender()) pPopupMenu->render();
		pPopupMenu->show(mousePos.x, mousePos.y);
		pPopupMenu->doHighlight(pPopupMenu->getCurrentItem());
	}
}

void LOK2ChatDisplay::addLine(std::vector < std::pair < int, std::string > > data) {
	m_Data.push_back(data);
	if(m_Data.size() > 50) m_Data.erase(m_Data.begin());
}
int LOK2ChatDisplay::makeLines(std::vector <std::pair < int, std::string > > data, int width) {
	string buffer = data[1].second;
	vLines.clear();
	bool hack = false;
	int w = 0, h = 0, i = 1;
	int i2;
	if(buffer.size() <= 0) return 0;
	do {
		if(hack) {
			vLines.pop_back();
			hack = false;
		}
		i = 1;
		do {
			TTF_SizeText(font, buffer.substr(0, i++).c_str(), &w, &h); 
		} while(w <= width && i < buffer.size());
		if(i > 0) {
			i2 = i;
			if(w >= width) {
				do { 
					i--;
				} while(buffer.substr(0, i).c_str()[buffer.substr(0, i).size() - 1] != ' ' && i >= 0);
				if(i > 0) {
					vLines.push_back(buffer.substr(0, i));
					vLines.push_back(buffer.substr(i, i2));
					buffer.erase(0, i);
					hack = true;
				} else {
					i = i2;
					i--;
					vLines.push_back(buffer.substr(0, i));
					buffer.erase(0, i);
					i = 1;
					vLines.push_back(buffer.substr(0, 1));
					hack = true;
				}
			} else  {
				vLines.push_back(buffer.substr(0, i));
				buffer.erase(0, i);
			}
		}
	} while(i < buffer.size());
	return vLines.size();
}

void LOK2ChatDisplay::inputHandler() {
//	if(event->type == SDL_MOUSEBUTTONDOWN) setFocus(true);
	if(hasFocus()) {
//	myButton->inputHandler();
		int x, y;
		int caretLocBuffer = 0;
		string temp;
		if(highlight.start != highlight.stop) { 
			pPopupMenu->setActive(POPUP_COPY, true);
		} else {
			pPopupMenu->setActive(POPUP_COPY, false);
		}
		if(str.size() > 0) {
			pPopupMenu->setActive(POPUP_SELECTALL, true);
		} else {
			pPopupMenu->setActive(POPUP_SELECTALL, false);
		}
		if(pPopupMenu->isVisible()) {
			SDL_SetCursor(normalCursor);
			pPopupMenu->inputHandler();
		} else {
			switch(event->type) {
		/*	case SDL_KEYDOWN:
				switch(event->key.keysym.sym) {
				case SDLK_BACKSPACE:
					if(str.length != 0 && caret.caretLoc > 0) {
						if(highlight.start != highlight.stop) {
							if(highlight.start > highlight.stop) {
								x = highlight.stop;
								y = highlight.start;
							} else {
								x = highlight.start;
								y = highlight.stop;
							}
							str.erase(x, y - x);
							caret.caretLoc = x;
							highlight.start = 0;
							highlight.stop = 0;
						} else {
							str.erase(caret.caretLoc - 1, 1);
							caret.caretLoc--;
						}
					}
					break;
				case SDLK_DELETE:
					if(caret.caretLoc < str.size()) {
						if(highlight.start != highlight.stop) {
							if(highlight.start > highlight.stop) {
								x = highlight.stop;
								y = highlight.start;
							} else {
								x = highlight.start;
								y = highlight.stop;
							}
							str.erase(x, y - x);
							caret.caretLoc = x;
							highlight.start = 0;
							highlight.stop = 0;
						} else str.erase(caret.caretLoc, 1);
					}
					break;
				case SDLK_HOME:
					caret.caretLoc = 0;
					break;
				case SDLK_END:
					caret.caretLoc = str.size();
					break;
				default:
					//left, right, up, down have to be in default so that ctrl-dir will work for highlighting.
					if(event->key.keysym.sym == SDLK_LEFT) if(caret.caretLoc > 0) caret.caretLoc--;
					if(event->key.keysym.sym == SDLK_RIGHT) if(caret.caretLoc < str.length()) caret.caretLoc++;
					if(event->key.keysym.sym == SDLK_UP) {
						if(findCharXY(caret.caretX, caret.caretY - caret.caretH / 2) > 0) caret.caretLoc = findCharXY(caret.caretX, caret.caretY - caret.caretH / 2);
						else caret.caretLoc = 0;
					}
					if(event->key.keysym.sym == SDLK_DOWN) {
						if(findCharXY(caret.caretX, caret.caretY + (caret.caretH + caret.caretH / 2)) > 0) caret.caretLoc = findCharXY(caret.caretX, caret.caretY + (caret.caretH + caret.caretH / 2));
						else caret.caretLoc = str.size();
					}

					if(str.length() <= max_len) {
						if(event->key.keysym.unicode >= 0x20 && event->key.keysym.unicode <= 0x7E) {
							temp = (char)event->key.keysym.unicode;
							str.insert(caret.caretLoc, temp);
							caret.caretLoc++;
						}
					}
					if(event->key.keysym.mod & KMOD_CTRL) {
						switch(event->key.keysym.sym) {
						case 'a':
							highlight.start = 1; //should be 0, fix when I go through and make 0 an acceptable index for highlighting
							highlight.stop = str.size();
							highlight.active = true;
							break;
						case 'c':
							if(highlight.start != highlight.stop) {
								if(highlight.start > highlight.stop) {
									x = highlight.stop;
									y = highlight.start;
								} else {
									x = highlight.start;
									y = highlight.stop;
								}
								if(str.substr(x, y - x).size() > 0) pClipboard->setData(str.substr(x, y - x));
							}
							break;
						case 'v':
							if(pClipboard->getData().size() > 0) {
								if(highlight.start == highlight.stop) {
									temp = pClipboard->getData();
									if(temp.size() > 0) {
										if(str.size() + temp.size() > max_len) {
											x = max_len - str.size();
											temp.erase(x, temp.size() - x);
										}
										str.insert(caret.caretLoc, temp);
										caret.caretLoc += temp.size();
									}
								} else {
									if(highlight.start > highlight.stop) {
										x = highlight.stop;
										y = highlight.start;
									} else {
										x = highlight.start;
										y = highlight.stop;
									}
									temp = str.substr(x, y - x);
									str.erase(x, y - x);
									caret.caretLoc = y;
									caret.caretLoc -= temp.size();
									temp = pClipboard->getData();
									if(str.size() + temp.size() > max_len) {
										x = max_len - str.size();
										temp.erase(x, temp.size() - x);
									}
									str.insert(caret.caretLoc, temp);
									highlight.start = 0;
									highlight.stop = 0;
									caret.caretLoc += temp.size();
								}
							}
							break;
						case 'x':
							if(highlight.start != highlight.stop) {
								if(highlight.start > highlight.stop) {
									x = highlight.stop;
									y = highlight.start;
								} else {
									x = highlight.start;
									y = highlight.stop;
								}
								if(str.substr(x, y - x).size() > 0) pClipboard->setData(str.substr(x, y - x));
								str.erase(x, y - x);
								caret.caretLoc = x;
								highlight.start = 0;
								highlight.stop = 0;
							}
							break;
						case SDLK_LEFT:
							if(highlight.active) {
								if(highlight.stop == caret.caretLoc + 1) {
									highlight.stop = caret.caretLoc;
								} else {
									highlight.start = caret.caretLoc + 1;
									highlight.stop = caret.caretLoc;
								}
							} else {
								highlight.start = caret.caretLoc + 1;
								highlight.stop = caret.caretLoc;
								highlight.active = true;
							}
							break;
						case SDLK_RIGHT:
							if(highlight.active) {
								if(highlight.stop == caret.caretLoc - 1) {
									highlight.stop = caret.caretLoc;
								} else {
									highlight.start = caret.caretLoc - 1;
									highlight.stop = caret.caretLoc;
								}
							} else {
								highlight.start = caret.caretLoc - 1;
								highlight.stop = caret.caretLoc;
								highlight.active = true;
							}
							break;
						case SDLK_UP:		//not too sure why up and down work the same here..
						case SDLK_DOWN:
							x = findCharXY(caret.caretX, caret.caretY + caret.caretH / 2);
							if(highlight.active) {
								if(highlight.stop == x - 1 || highlight.stop == x + 1 || highlight.stop == x) {
									highlight.stop = caret.caretLoc;
								} else {
									highlight.start = x;
									highlight.stop = caret.caretLoc;
								}
							} else {
								highlight.start = x;
								highlight.stop = caret.caretLoc;
								highlight.active = true;
							}
							break;
						case 'k':
							str.erase();
							caret.caretLoc = 0;
							highlight.active = false;
							highlight.start = 0;
							highlight.stop = 0;
							break;
						}
					}
				}
				break;*/
			case SDL_MOUSEBUTTONDOWN:
				switch(event->button.button) {
				case SDL_BUTTON_LEFT:
					x = event->button.x;
					y = event->button.y;
					if((x > box.x) && (x < box.x + box.w) && (y > box.y) && (y < box.y + box.h)) {
					/*	caretLocBuffer = findCharXY(x, y);
						if(caretLocBuffer) {
							caret.caretLoc = caretLocBuffer;
							if(!highlight.active) {
								highlight.start = 0;
								highlight.stop = 0;
								highlight.start = caretLocBuffer;
								highlight.active = true;
							}
						}*/
						pManager->requestLock(this);
						if(pPopupMenu->isVisible()) pPopupMenu->hide();
					} else pManager->releaseLock(this);
					break;
				case SDL_BUTTON_RIGHT:
					x = event->button.x;
					y = event->button.y;
					if((x > box.x) && (x < box.x + box.w) && (y > box.y) && (y < box.y + box.h)) {
						pManager->requestLock(this);
						mousePos.x = x;
						mousePos.y = y;
						if(pPopupMenu->mustRender()) pPopupMenu->render();
						pPopupMenu->show(mousePos.x, mousePos.y);
					} else pManager->releaseLock(this);
					break;
				}
				break;
			case SDL_MOUSEMOTION:
				x = event->motion.x;
				y = event->motion.y;
				if((x > box.x) && (x < box.x + box.w) && (y > box.y) && (y < box.y + box.h)) {
					SDL_SetCursor(textCursor);
				} else {
					SDL_SetCursor(normalCursor);
				}
				if(event->motion.state & SDL_BUTTON(1)) {
					if((x > box.x) && (x < box.x + box.w) && (y > box.y) && (y < box.y + box.h)) {
						if(!highlight.active) {
							highlight.start = 0;
							highlight.stop = 0;
							caretLocBuffer = findCharXY(x, y);
							if(caretLocBuffer) highlight.start = caretLocBuffer;
							highlight.active = true;
						} else if(highlight.active) {
							caretLocBuffer = findCharXY(x, y);
							if(caretLocBuffer) highlight.stop = caretLocBuffer;
							caret.caretLoc = caretLocBuffer;
						}
					}
				}
				break;
			/*case SDL_MOUSEBUTTONUP:
				if(event->button.button == SDL_BUTTON_LEFT) {
					x = event->button.x;
					y = event->button.y;
					if(highlight.active) {
						caretLocBuffer = findCharXY(x, y);
						if(caretLocBuffer) highlight.stop = caretLocBuffer;
						highlight.active = false;
					} else {
						highlight.start = 0;
						highlight.stop = 0;
					}
				}
				break;*/
			default:
				//unknown event
				break;
			}
		}
	}
}

SDL_Rect LOK2ChatDisplay::getRect() {
	return box;
}

void LOK2ChatDisplay::doAction(int handle, int message) {
	switch(handle) {
	case HSCROLLBAR:
		if(message == SCROLLBARUP) {
			printf("Scroll up pressed\n");
			setScrollStart(1);
		} else if(message == SCROLLBARDOWN) {
			printf("Scroll down pressed\n");
			setScrollStart(-1);
		}
	}
}

void LOK2ChatDisplay::setScrollStart(int start) {
	m_ScrollStart += start;
}